package application

import (
	"github.com/gin-gonic/gin"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/disk"
	"github.com/shirou/gopsutil/host"
	"github.com/shirou/gopsutil/mem"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"ruoyi/domain/entity/monitor"
	"ruoyi/domain/repository"
	"ruoyi/utils"
	"strings"
	"time"
)

type ServiceApp struct {
	role repository.ServiceRepository
}

var _ ServiceAppInterface = &ServiceApp{}

type ServiceAppInterface interface {
	GetServerInfo(context *gin.Context) monitor.Server

	GetAppPath() string
}

func (s *ServiceApp) GetServerInfo(context *gin.Context) monitor.Server {
	ip := utils.GetRemoteClientIp(context.Request)

	var server monitor.Server
	server.Cpu = getCpu()
	server.Jvm = getJvm()
	server.Mem = getMem()
	server.Sys = s.getSys(ip)
	server.SysFile = getSysFile()
	return server
}

func getCpu() monitor.Cpu {
	cpuCount, _ := cpu.Counts(true) //cpu逻辑数量
	return monitor.Cpu{
		CpuNum: runtime.NumCPU(),
		Total:  cpuCount,
		Sys:    "",
		Used:   getCpuPercent(),
		Wait:   "",
		Free:   "",
	}
}
func getCpuPercent() float64 {
	percent, _ := cpu.Percent(time.Second, false)
	return percent[0]
}

func getJvm() monitor.Jvm {
	info, _ := mem.VirtualMemory()
	return monitor.Jvm{
		Total:   info.Total,
		Max:     info.HighTotal,
		Free:    info.Free,
		Version: "",
		Home:    "",
	}
}

func getMem() monitor.Mem {
	info, _ := mem.VirtualMemory()
	return monitor.Mem{
		Total: info.Total,
		Used:  info.Used,
		Free:  info.Total - info.Used,
	}
}

func (s *ServiceApp) getSys(ip string) monitor.Sys {
	info, _ := host.Info()
	return monitor.Sys{
		ComputerName: info.Hostname,
		ComputerIp:   ip,
		UserDir:      s.GetAppPath(),
		OsName:       info.OS,
		OsArch:       runtime.GOARCH,
	}
}

// GetAppPath 获取运行时的相对目录
func (s *ServiceApp) GetAppPath() string {
	file, _ := exec.LookPath(os.Args[0])
	path, _ := filepath.Abs(file)
	index := strings.LastIndex(path, string(os.PathSeparator))

	return path[:index]
}

func getSysFile() []monitor.SysFile {
	var sysFiles []monitor.SysFile
	infos, _ := disk.Partitions(true) //所有分区
	for i := 0; i < len(infos); i++ {
		var info = infos[i]
		info2, _ := disk.Usage(info.Mountpoint) //指定某路径的硬盘使用情况
		var sysFile = monitor.SysFile{
			DirName:     info2.Path,
			SysTypeName: info.Fstype,
			TypeName:    "",
			Total:       utils.FormatFileSize(info2.Total),
			Free:        info2.Free,
			Used:        info2.Used,
			Usage:       info2.UsedPercent,
		}
		sysFiles = append(sysFiles, sysFile)
	}
	return sysFiles
}
